<?php
namespace core\models;
/**
 * RPC客户端【Yar】
 * @package core\models
 * @author  ZhouHaoHua <53027327@qq.com>
 * @package
 */
class Rpc_C_Yar implements Interface_Rpc_Client {
    private $client;

    /**
     * 创建一个客户端实例
     * @param string $uri 服务端的URI路径.
     * @param string $protocol
     */
    public function __construct($uri, $protocol = 'http') {
        $this->client = new \Yar_Client($uri);
    }

    /**
     * 调用远程服务
     * @param string $method     远程服务的名字
     * @param array  $parameters 调用参数。如远程有一个方法是acb($a, $b)，本地参数就要写成 array($a, $b)
     * @return mixed
     * @author ZhouHaoHua <53027327@qq.com>
     */
    public function call($method, array $parameters) {
        return $this->client->call($method, $parameters);
    }

    /**
     * 设置配置。比如设置超时时间、返回的数据类型等
     * @param string|array $name  。可有：timeout, packager, connect_timeout, persistent。或数组形式:key为名称 val为值，如：['timeout'=>1000, 'packager'=>"json", 'connect_timeout' => 3600000]
     * @param mixed        $value 具体的值，如果$name为数组此值就没有用。
     * @return mixed
     * @author ZhouHaoHua <53027327@qq.com>
     * @see    http://php.net/manual/zh/yar-client.setopt.php
     */
    public function setOpt($name, $value = null) {
        if (is_string($name)) {
            return $this->client->SetOpt(constant('YAR_OPT_' . strtoupper($name)), $value);
        } elseif (is_array($name)) {
            $r = array();
            foreach ($name as $k => $v) {
                $r[] = $this->client->SetOpt(constant('YAR_OPT_' . strtoupper($k)), $v);
            }
            return $r;
        }
        return false;
    }

    /**
     * 调用远程服务【多线程】
     * @param string $uri        远程服务的URL
     * @param string $method     调用的服务名字(也就是服务方法名)
     * @param array  $parameters 调用参数。如远程有一个方法是acb($a, $b)，本地参数就要写成 array($a, $b)
     * @param string $callback   回调函数的名字
     * @return int 注意：当全部调用完以后要用loopConcurrent方法真正执行发送
     * @author ZhouHaoHua <53027327@qq.com>
     */
    public function callConcurrent($uri, $method, array $parameters, $callback = null) {
        return \Yar_Concurrent_Client::call($uri, $method, $parameters, $callback/*, null, array(YAR_OPT_TIMEOUT => 1000000, YAR_OPT_CONNECT_TIMEOUT=>1000000)*/);
    }

    /**
     * 发送所有注册的callConcurrent【多线程】调用
     * @param string $error_callback 错误回调函数, 如果设置了, 那么在出错的时候会调用这个回调函数.
     * @return boolean
     * @author ZhouHaoHua <53027327@qq.com>
     */
    public function loopConcurrent($error_callback = null) {
        //$error_callback;
        $r = \Yar_Concurrent_Client::loop(null, $error_callback);
        $this->resetConcurrent();
        return $r;
    }

    /**
     * 清除所有已经callConcurrent了的方法【多线程】
     * @return boolean
     * @author ZhouHaoHua <53027327@qq.com>
     */
    public function resetConcurrent() {
        return \Yar_Concurrent_Client::reset();
    }

}